package com.oa.erp.pur.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.mdp.core.err.BizException;
import com.mdp.core.service.BaseService;
import com.mdp.core.utils.BaseUtils;
import com.mdp.safe.client.entity.User;
import com.mdp.safe.client.utils.LoginUtils;
import com.oa.erp.pur.entity.Require;
import com.oa.erp.pur.entity.RequireDetail;
import com.oa.erp.pur.mapper.RequireMapper;
import com.oa.erp.pur.vo.RequireAddVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * @author maimeng-mdp code-gen
 * @since 2023年10月8日
 */
@Service
public class RequireService extends BaseService<RequireMapper, Require> {
    static Logger logger = LoggerFactory.getLogger(RequireService.class);

    /**
     * 自定义查询，支持多表关联
     *
     * @param page 分页条件
     * @param ew   一定要，并且必须加@Param("ew")注解
     * @param ext  如果xml中需要根据某些值进行特殊处理，可以通过这个进行传递，非必须，注解也可以不加
     * @return
     */
    public List<Map<String, Object>> selectListMapByWhere(IPage page, QueryWrapper ew, Map<String, Object> ext) {
        return baseMapper.selectListMapByWhere(page, ew, ext);
    }

    @Autowired
    private RequireDetailService requireDetailService;

    /**
     * 添加资产申购单
     *
     * @param requireAddVo
     */
    @Transactional
    public void insertRequire(RequireAddVo requireAddVo) {
        User user = LoginUtils.getCurrentUserInfo();
        //添加资产申购单主表
        Require source = requireAddVo.getPurRequire();
        //设置申购机构编号，与名称
        source.setReqBranchId(user.getBranchId());
        source.setReqBranchName(user.getBranchName());
        this.insert(source);

        //设置资产申购明细表
        List<RequireDetail> batchInsertDetails = new ArrayList<>();
        for (RequireDetail requireDetail : requireAddVo.getPurRequireDetail()) {
            //设置关联申购单主表Id
            requireDetail.setRequireId(source.getId());
            requireDetail.setId(requireDetailService.createKey("id"));
            //设置创建人
            requireDetail.setCreateUserid(user.getUserid());
            //设置创建时间
            requireDetail.setCreateTime(new Date());
            batchInsertDetails.add(requireDetail);
        }
        if (batchInsertDetails.size() > 0) {

            requireDetailService.batchInsert(batchInsertDetails);
        }
    }

    /**
     * 删除资产申购单以及明细
     *
     * @param require
     */
    @Transactional
    public void deleteRequire(Require require) {
        //1.删除资产申购单主表数据
        this.deleteByPk(require);
        Map<String, Object> params = new HashMap<>();
        params.put("requireId", require.getId());
        //删除资产申购单明细表数据
//		requireDetailService.deleteByWhere(params);
        requireDetailService.deleteByWhere(BaseUtils.fromMap(params, RequireDetail.class));
    }

    /**
     * 更新资产申报
     *
     * @param requireAddVo
     */
    @Transactional
    public void updateRequire(RequireAddVo requireAddVo) {
        //1.修改申购主表
        this.updateByPk(requireAddVo.getPurRequire());
        //2.批量修改申购明细表
        //设置资产申购明细表
        User user = LoginUtils.getCurrentUserInfo();
        List<RequireDetail> batchInsertDetails = new ArrayList<>();
        List<RequireDetail> batchUpdateDetails = new ArrayList<>();
        List<RequireDetail> batchDelDetails = new ArrayList<>();
        Date lastEditTime = new Date();
        RequireDetail query = new RequireDetail();
        query.setRequireId(requireAddVo.getPurRequire().getId());
        List<RequireDetail> requireDetailsDb = this.requireDetailService.selectListByWhere(query);
        List<RequireDetail> requireDetails = requireAddVo.getPurRequireDetail();
        for (RequireDetail requireDetail : requireDetailsDb) {
            if (!requireDetails.stream().filter(i -> requireDetail.getId().equals(i.getId())).findAny().isPresent()) {
                batchDelDetails.add(requireDetail);
            }
        }
        for (RequireDetail requireDetail : requireAddVo.getPurRequireDetail()) {
            requireDetail.setLastEditTime(new Date());
            requireDetail.setLastEditUserid(user.getUserid());
            requireDetail.setRequireId(requireAddVo.getPurRequire().getId());
            requireDetail.setLastEditTime(lastEditTime);
            //设置创建人
            requireDetail.setCreateUserid(user.getUserid());
            //设置创建时间
            if (null == requireDetail.getCreateTime()) {
                requireDetail.setCreateTime(new Date());
            }

            if (requireDetailsDb.stream().filter(i -> i.getId().equals(requireDetail.getId())).findAny().isPresent()) {
                batchUpdateDetails.add(requireDetail);
            } else {
                requireDetail.setId(requireDetailService.createKey("id"));
                batchInsertDetails.add(requireDetail);
            }
        }
        if (batchInsertDetails != null && batchInsertDetails.size() > 0) {
            requireDetailService.batchInsert(batchInsertDetails);
        }
        if (batchUpdateDetails != null && batchUpdateDetails.size() > 0) {
            requireDetailService.batchUpdate(batchUpdateDetails);
        }
        if (batchDelDetails != null && batchDelDetails.size() > 0) {
            this.requireDetailService.batchDelete(batchDelDetails);
        }

    }

    /**
     * 批量删除
     *
     * @param requires
     */
    @Transactional
    public void batchDeleteRequire(List<Require> requires) {
        //1.删除资产申购单主表数据
        this.batchDelete(requires);
        //删除资产申购单明细表数据
//		requireDetailService.batchDelete("batchDeleteDetailByRequireId", requires);
        baseMapper.deleteBatchIds(requires);
    }


    /** 请在此类添加自定义函数 */

    /**
     * 流程审批过程中回调该接口，更新业务数据
     * 如果发起流程时上送了restUrl，则无论流程中是否配置了监听器都会在流程发生以下事件时推送数据过来
     * eventName: PROCESS_STARTED 流程启动完成 全局
     * PROCESS_COMPLETED 流程正常结束 全局
     * PROCESS_CANCELLED 流程删除 全局
     * create 人工任务启动
     * complete 人工任务完成
     * assignment 人工任务分配给了具体的人
     * delete 人工任务被删除
     * TASK_COMPLETED_FORM_DATA_UPDATE 人工任务提交完成后，智能表单数据更新
     * <p>
     * 其中 create/complete/assignment/delete事件是需要在模型中人工节点上配置了委托代理表达式 ${taskBizCallListener}才会推送过来。
     * 在人工任务节点上配置 任务监听器  建议事件为 complete,其它assignment/create/complete/delete也可以，一般建议在complete,委托代理表达式 ${taskBizCallListener}
     *
     * @param flowVars {flowBranchId,agree,procInstId,startUserid,assignee,actId,taskName,mainTitle,branchId,bizKey,commentMsg,eventName,modelKey} 等
     * @return 如果tips.isOk==false，将影响流程提交
     **/
    @Transactional
    public void processApprova(IPage page, QueryWrapper ew, Map<String, Object> flowVars) {
        String eventName = (String) flowVars.get("eventName");
        String agree = (String) flowVars.get("agree");
        String branchId = (String) flowVars.get("branchId");
        String purRequireId = (String) flowVars.get("purRequireId");//资产申购单编号
        String bizKey = (String) flowVars.get("bizKey");
        if ("asset_require_process_approva".equals(bizKey)) {
        } else {
            throw new BizException("不支持的业务,请上送业务编码【bizKey】参数");
        }

        if ("complete".equals(eventName)) {
            if ("1".equals(agree)) {
                this.updateFlowStateByProcInst(null, flowVars);
            } else {
                this.updateFlowStateByProcInst(null, flowVars);
            }
        } else {
            if ("PROCESS_STARTED".equals(eventName)) {
                Map<String, Object> bizQuery = new HashMap<>();
                bizQuery.put("id", purRequireId);
                if (StringUtils.isEmpty(purRequireId)) {
                    throw new BizException("请上送资产申购单编号-purOrderId");
                }
                if (StringUtils.isEmpty(branchId)) {
                    throw new BizException("请上送branchId");
                }
                List<Map<String, Object>> bizList = this.selectListMapByWhere(page, ew, bizQuery);
                if (bizList == null || bizList.size() == 0) {
                    throw new BizException("没有找到对应资产申购单,采购单为【" + purRequireId + "】");
                } else {
                    Map<String, Object> bizObject = bizList.get(0);
                    if ("1".equals(bizObject.get("bizFlowState"))) {
                        throw new BizException("该资产申购单正在审批中，不能再发起审批");
                    }
                }
                this.updateFlowStateByProcInst("1", flowVars);
            } else if ("PROCESS_COMPLETED".equals(eventName)) {
                //流程表、订单表更新
                flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                if ("1".equals(agree)) {
                    //permit为审批通过状态
                    this.updateFlowStateByProcInst("2", flowVars);
                } else {
                    //reject为未通过状态
                    this.updateFlowStateByProcInst("3", flowVars);
                }
            } else if ("PROCESS_CANCELLED".equals(eventName)) {
                //cancel为流程取消状态
                flowVars.put("flowEndTime", new Date());//传入任意数值，表示flowEndTime需要修改
                this.updateFlowStateByProcInst("4", flowVars);
            }
        }

    }

    //update等级表状态、流程表信息
    public void updateFlowStateByProcInst(String flowState, Map<String, Object> flowVars) {
        flowVars.put("bizFlowState", flowState);
        flowVars.put("reqStatus", flowState);
        flowVars.put("id", flowVars.get("purRequireId"));
        if ("1".equals(flowState)) {
            flowVars.put("bizFLowState", flowState);
            flowVars.put("bizProcInstId", flowVars.get("procInstId"));
        }
        this.updateSomeFieldByPk(BaseUtils.fromMap(flowVars, Require.class));
    }

    public List<Require> selectListByDetailIds(List<String> detailIds) {
        return baseMapper.selectListByDetailIds(detailIds);
    }
}

